﻿#region Header
// ------------------------ Licence / Copyright ------------------------
// 
// ScrumTable for Scrum Meeting Support
// Copyright © HSR - Hochschule für Technik Rapperswil
// All Rights Reserved
// 
// Author:
//  Michael Gfeller Silvan Gehrig Patrick Boos
// 
// ---------------------------------------------------------------------
#endregion

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ScrumTable.Common.Collections;
using ScrumTable.Config.UserManagement;

namespace ScrumTable.Config.Test.UserManagement
{
    /// <summary>
    /// This is the test class for LoginAccountManager class.
    /// </summary>
    [TestClass]
    public class LoginAccountTest
    {
        #region Declarations
        //--------------------------------------------------------------------
        // Declarations
        //--------------------------------------------------------------------

        private LoginAccountManager _context;
        private const long Id = 0x156015;
        private const string ServerPwd = "testpwd1234";
        private const string ServerLogin = "MyName";
        private const string Pin = "_1234_";
        private const string Servername = "TFS";

        #endregion

        #region Properties
        //--------------------------------------------------------------------
        // Properties
        //--------------------------------------------------------------------

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext { get; set; }

        #endregion

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        #region Constructors / Destructor
        //--------------------------------------------------------------------
        // Constructors / Destructor
        //--------------------------------------------------------------------

        /// <summary>
        /// Creates a new DomainContextFactoryTest instance.
        /// </summary>
        public LoginAccountTest()
        {
        }

        #endregion

        #region Methods
        //--------------------------------------------------------------------
        // Methods
        //--------------------------------------------------------------------

        /// <summary>
        /// Use TestInitialize to run code before running each test .
        /// </summary>
        [TestInitialize]
        public void TestInitialize()
        {
            _context = LoginAccountManagerFactory.CreateUserManager();
            _context.AddUser(Id);
            _context.GetLoginAccount(Id).SetLogin(ServerLogin, ServerPwd);
            _context.GetLoginAccount(Id).ServerName = Servername;
        }

        /// <summary>
        /// Use TestCleanup to run code after each test has run.
        /// </summary>
        [TestCleanup]
        public void TestCleanup()
        {
            _context = null;
        }

        [TestMethod]
        public void TestSetCurrentUser()
        {
          
            _context.SetCurrentLoginAccount(Id);
            Assert.IsTrue(_context.CurrentLoginAccount.IdentityTagValue == Id);
        }

        [TestMethod]
        public void TestAddSetUser()
        {

            int count = _context.UserList.Count;
            const int countNewTags = 5;
            for (int i = 0; i < countNewTags; i++)
            {
                _context.AddAndSetLoginAccount();
            }
            var idTagList = (from x in _context.UserList select x.IdentityTagValue).Distinct();
            Assert.IsTrue(idTagList.Count() == count + countNewTags);
        }

        [TestMethod]
        public void TestSecurity()
        {
            ILoginAccount loginAccount = _context.GetLoginAccount(Id);
            Assert.AreEqual(loginAccount.DeCryptedLogins[0].Right, ServerPwd);
            loginAccount.Pin = Pin;
            Assert.AreEqual(loginAccount.DeCryptedLogins.Count, 0);
            Assert.AreNotEqual(loginAccount.CryptedLogins[0].Right, ServerPwd);
            loginAccount.Decrypt(Pin);
            Assert.AreEqual(loginAccount.DeCryptedLogins[0].Right, ServerPwd);
        }

        [TestMethod]
        public void TestChangeAdd()
        {
            const string newServerPwd = "MyPwd";
            const string newPin = "NewPin";
            LoginAccount loginAccount = _context.GetLoginAccount(Id);
            List<SerializablePair<string, string>> newList = new List<SerializablePair<string, string>>(loginAccount.DeCryptedLogins);

            loginAccount.Pin = Pin;
            newList.Add(new SerializablePair<string, string>("NewUser", newServerPwd));
            loginAccount.ChangeLogins(newList, Pin);
            loginAccount.Pin = newPin;
            loginAccount.Decrypt(newPin);

            newList.Add(new SerializablePair<string, string>("NewUser2", newServerPwd+"2"));
            loginAccount.ChangeLogins(newList, Pin);
            loginAccount.Pin = newPin;
            loginAccount.Decrypt(newPin);

            var x = loginAccount.DeCryptedLogins;
            Assert.AreEqual(x[0].Right, ServerPwd);
            Assert.AreEqual(x[1].Right, newServerPwd);
            Assert.AreEqual(x[2].Right, newServerPwd+"2");
        }


        [TestMethod]
        public void TestChangeRemove()
        {
            const string newServerPwd = "MyPwd";
            const string newPin = "NewPin";
            LoginAccount loginAccount = _context.GetLoginAccount(Id);
            List<SerializablePair<string, string>> newList = new List<SerializablePair<string, string>>(loginAccount.DeCryptedLogins);

            loginAccount.Pin = Pin;
            newList.Add(new SerializablePair<string, string>("NewUser", newServerPwd));
            loginAccount.ChangeLogins(newList, Pin);
            loginAccount.Pin = newPin;
            loginAccount.Decrypt(newPin);

            newList.RemoveAt(0);
            loginAccount.ChangeLogins(newList, Pin);
            loginAccount.Pin = newPin;
            loginAccount.Decrypt(newPin);

            var x = loginAccount.DeCryptedLogins;
            Assert.AreEqual(x[0].Right, newServerPwd);
        }


        [TestMethod]
        public void TestChangeWithWrongFirstPin()
        {
            const string newServerPwd = "MyPwd";
            const string newPin = "NewPin";
            LoginAccount loginAccount = _context.GetLoginAccount(Id);
            List<SerializablePair<string, string>> newList = new List<SerializablePair<string, string>>(loginAccount.DeCryptedLogins);

            loginAccount.Pin = Pin;
            newList[0].Right = LoginAccount.HiddenPassword;
            newList.Add(new SerializablePair<string, string>("NewUser", newServerPwd));
            loginAccount.ChangeLogins(newList, newPin);
            loginAccount.Pin = newPin;
            loginAccount.Decrypt(newPin);
            
            var x = loginAccount.DeCryptedLogins;
            Assert.AreNotEqual(x[0].Right, ServerPwd);
            Assert.AreEqual(x[1].Right, newServerPwd);

            loginAccount.ChangeLogins(newList, Pin);
            //loginAccount.Decrypt(Pin);
            x = loginAccount.DeCryptedLogins;

            Assert.AreEqual(x[0].Right, ServerPwd);
            Assert.AreEqual(x[1].Right, newServerPwd);
        }

        [TestMethod]
        public void TestWrongPin()
        {
            _context.GetLoginAccount(Id).Pin = Pin;
            _context.GetLoginAccount(Id).Decrypt("x" + Pin + "x");
            Assert.AreNotEqual(_context.GetLoginAccount(Id).DeCryptedLogins[0].Right, ServerPwd);
        }

        [TestMethod]
        public void TestSave()
        {

            string file = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.InternetCache), "test.xml");
            _context.GetLoginAccount(Id).Pin = Pin;
            _context.SaveLogin(file);
            var tmpManager = LoginAccountManagerFactory.CreateUserManager(file, file);
            Assert.IsTrue(tmpManager.ContainsLoginAccount(Id));
            
        }

        #endregion

        #region Events
        //--------------------------------------------------------------------
        // Events
        //--------------------------------------------------------------------

        #endregion
    }
}